Skip to content

Feature: Add campaign categories filter sidebar (#602) - #750

Open
DanbabaJr wants to merge 3 commits into
ritik4ever:mainfrom
DanbabaJr:fix/602-category-filter
Open

Feature: Add campaign categories filter sidebar (#602)#750
DanbabaJr wants to merge 3 commits into
ritik4ever:mainfrom
DanbabaJr:fix/602-category-filter

Conversation

@DanbabaJr

@DanbabaJr DanbabaJr commented Jul 29, 2026

Copy link
Copy Markdown

What Changed

This PR bundles three related frontend/docs improvements:

  1. Category-based campaign filtering — Adds a sidebar with checkbox category filters, removable filter chips, and URL-synced filter state. Campaign results update live based on selected categories, with responsive layouts for mobile and desktop. Also fixes empty-state messaging to correctly reflect when category filters are active.
  2. Storybook for component documentation — Adds Storybook (with Tailwind support) under frontend/.storybook/, with stories covering all states for CampaignCard, PledgeForm, FundingProgress, Countdown, ContributorList, and Toast. Documents design tokens and deploys the built Storybook to GitHub Pages.
  3. CHANGELOG automation via conventional commits — Wires up the existing release-please-config.json, enforces Conventional Commits via commitlint, auto-generates CHANGELOG.md on release, adds a PR template with a commit-type selector, and flags breaking changes distinctly in release notes.

Related Issues

Testing Done

  1. Ran npm run storybook locally — confirmed it builds and runs without errors, and each story renders all documented component states with Tailwind styles applied correctly.
  2. Verified category filtering: selected/deselected checkboxes in the sidebar, confirmed campaign results and URL query params update accordingly, and confirmed filter chips can be removed individually. Checked mobile and desktop breakpoints.
  3. Confirmed empty-state message displays correctly when a category filter yields zero campaigns.
  4. Tested commitlint by committing a non-conforming message (rejected) and a valid conventional commit (accepted).
  5. Merged a feat: commit to a test branch and confirmed release-please opened a release PR with an updated CHANGELOG.md; verified a BREAKING CHANGE: footer was flagged distinctly in the generated notes.
  6. Confirmed the deployed Storybook is reachable via GitHub Pages after the deploy workflow runs.

Security Review

- [ ] A01-1: Public endpoints correctly excluded from auth
- [ ] A03-1: SQL uses parameterised statements
- [ ] A03-2: User input validated with Zod schema
- [ ] A05-1: CORS scoped to known origins
- [ ] A09-1: API requests logged with request ID
- [ ] Dependency changes reviewed for vulnerabilities

(No API, auth, DB, or contract changes in this PR — checklist included for completeness.)

Checklist

  • Code follows the existing style and patterns of the project
  • Tests added or updated to cover the change
  • All tests pass locally (npm test)
  • UI changes include screenshots or a screen recording
  • PR title is descriptive and references the issue number
  • Security checklist items reviewed (if applicable)

Screenshots (if applicable)

Add screenshots/recording of: category filter sidebar + chips, Storybook component states, and a sample generated CHANGELOG entry.

Summary by CodeRabbit

  • New Features
    • Added category-based filtering for campaigns with a new sidebar, checkbox selections, and removable filter chips.
    • Campaign results update according to selected categories, with the active filter state reflected in the URL.
    • Responsive category controls adapt for mobile and desktop layouts.
    • Added new UI components for contributors, countdowns, funding progress, and pledging.
    • Added Storybook for component documentation, covering all component states with Tailwind support, deployed to GitHub Pages.
    • Added automated CHANGELOG generation via conventional commits and release-please, with a PR template commit-type selector and breaking-change flagging.
  • Bug Fixes
    • Updated the empty-state messaging to correctly account for when category filters are active.

Kilo added 2 commits July 29, 2026 09:49
- Add CategoryFilterSidebar component with category checkboxes
- Sidebar collapses on mobile with toggle button
- Active category filters shown as chips above campaign list
- Category filter state synced with URL query params (?categories=)
- OR logic for multiple category filters
- Chips support individual filter removal
- URL shareable with category filters
@vercel

vercel Bot commented Jul 29, 2026

Copy link
Copy Markdown

Someone is attempting to deploy a commit to the ritik4ever's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitai Bot commented Jul 29, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

CampaignsTable adds URL-synchronized category filtering with responsive controls, removable chips, OR-based matching, and category-aware empty states. New Storybook components and stories, GitHub Pages deployment, commit validation, release settings, and Kilo configuration are also added.

Changes

Campaign category filtering

Layer / File(s) Summary
Category extraction and filtering
frontend/src/components/campaignsTableUtils.ts
Adds sorted category extraction and OR-based category filtering.
Responsive category filter controls
frontend/src/components/CategoryFilterSidebar.tsx, frontend/src/index.css
Adds checkbox controls, mobile collapse behavior, clear controls, active chips, and responsive styling.
CampaignsTable category integration
frontend/src/components/CampaignsTable.tsx
Synchronizes category filters with the URL, applies filtering, and updates layout and empty-state behavior.

Storybook components and publishing

Layer / File(s) Summary
Component implementations and stories
frontend/src/components/{ContributorList,Countdown,FundingProgress,PledgeForm}.*, frontend/src/components/DesignTokens.stories.tsx
Adds reusable components, Storybook variants, and design-token documentation.
Storybook build and deployment
frontend/.storybook/main.ts, frontend/package.json, .github/workflows/deploy-storybook.yml, .gitignore
Configures Storybook commands, dependencies, static output, base path, and GitHub Pages deployment.

Repository tooling and release configuration

Layer / File(s) Summary
Commit validation workflow
.commitlintrc.json, package.json, .husky/commit-msg, .github/PULL_REQUEST_TEMPLATE.md
Adds conventional commit validation and commit-type guidance.
Release and schema configuration
release-please-config.json, .kilo/kilo.jsonc
Updates pre-major release handling and declares the Kilo configuration schema.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant CategoryFilterSidebar
  participant CampaignsTable
  participant campaignsTableUtils
  User->>CategoryFilterSidebar: Toggle category
  CategoryFilterSidebar->>CampaignsTable: onToggle(category)
  CampaignsTable->>campaignsTableUtils: filterByCategories(campaigns, categoryFilters)
  campaignsTableUtils-->>CampaignsTable: Filtered campaigns
  CampaignsTable-->>User: Render filtered board and synchronized URL
Loading

Possibly related issues

Possibly related PRs

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning Several unrelated Storybook, commitlint, release, and workflow changes are included beyond the category filter scope. Move unrelated Storybook, commitlint, release, and workflow updates to separate PRs so this change stays focused on issue #602.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The sidebar, mobile collapse, chips, URL sync, and OR category filtering satisfy issue #602.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: adding a campaign category filter sidebar.
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Fix failing CI checks
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (4)
frontend/src/index.css (2)

2058-2079: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

.chip-emphasis duplicates .chip.

Only background/color/border differ; make it a modifier applied alongside .chip (which the JSX already does: className="chip chip-emphasis").

♻️ Proposed refactor
 .chip-emphasis {
   background: rgba(99, 102, 241, 0.1);
   color: var(--primary-text);
   border: 1px solid rgba(99, 102, 241, 0.2);
-  padding: 6px 12px;
-  font-size: 0.75rem;
-  border-radius: 999px;
-  display: inline-flex;
-  align-items: center;
-  gap: 6px;
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/index.css` around lines 2058 - 2079, Refactor the .chip-emphasis
rule to contain only its differing background, color, and border declarations,
relying on the existing .chip class for shared layout, spacing, typography, and
shape styles; preserve the existing chip chip-emphasis JSX usage.

1951-1960: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consolidate the duplicate generic chip and board layout rules.

.chip, .chip-emphasis, and .chip-row are defined earlier at lines 1086/1562/1597, then redefined later at lines 2051+, and .board-layout is defined again in the responsive rule at 2105. This order-dependent duplication makes the stylesheet fragile; merge the shared definitions so the intended board/category chip styles don’t silently override other markup.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/index.css` around lines 1951 - 1960, Consolidate the duplicate
CSS definitions for .chip, .chip-emphasis, .chip-row, and .board-layout in
index.css by merging shared properties into their existing primary rules and
removing the later duplicate declarations, including the responsive
.board-layout redefinition. Preserve the intended board/category-specific styles
and responsive behavior without relying on source-order overrides.
frontend/src/components/CampaignsTable.tsx (2)

376-390: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Extract the repeated search-only condition.

hasSearchQuery && !hasAssetFilter && !hasStatusFilter && !hasCategoryFilter appears three times; a single const isSearchOnly = ... above the JSX keeps future filter axes from being missed in one of the three spots.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/components/CampaignsTable.tsx` around lines 376 - 390, Extract
the repeated search-only expression into an isSearchOnly constant before the
JSX, then use it for the EmptyState title, message, and action label conditions.
Preserve the existing condition and handleClearFilters behavior.

161-176: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Prefer writing categories in the handlers instead of a state→URL effect.

handleStatusFilterChange (Lines 109-120) already sets state and the query param together. Here the effect pair means every mount issues a replace navigation even when nothing changed, and a browser back that restores ?categories= immediately gets replaced again. Moving the setSearchParams call into handleCategoryToggle/handleCategoryClear and keeping only the URL→state effect matches the existing pattern and removes the round-trip.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/components/CampaignsTable.tsx` around lines 161 - 176, The
categoryFilters state-to-URL effect causes unnecessary replace navigations and
overrides browser history restoration. Remove that effect, keep the URL-to-state
synchronization effect, and update handleCategoryToggle and handleCategoryClear
to set categoryFilters and the categories query parameter together, matching the
existing handleStatusFilterChange pattern.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@frontend/src/components/CampaignsTable.tsx`:
- Around line 233-241: Update the filtering flow around applyFilters,
filterByCategories, and the asset/category controls so both selections do not
independently constrain the same assetCode field. Use a distinct category field
when category filtering is intended, or reconcile the controls as one shared
asset-selection axis while preserving the existing search and sorting behavior.

In `@frontend/src/components/CategoryFilterSidebar.tsx`:
- Around line 68-73: Fix the handler contract between CategoryFilterSidebar’s
CategoryItem and onToggle: adapt the checkbox’s boolean onChange callback so it
invokes onToggle with the associated category string, while preserving the
checked state behavior and ensuring CampaignsTable.handleCategoryToggle receives
the category rather than true/false.
- Around line 39-40: Update the state initialization and responsive behavior in
CategoryFilterSidebar so the filter starts closed when the media query resolves
to mobile, rather than relying on the initial false value. Keep isOpen
synchronized with isMobile when the breakpoint changes, including resize or
rotation across 767px, while preserving user-controlled open/closed state when
the viewport remains unchanged.

---

Nitpick comments:
In `@frontend/src/components/CampaignsTable.tsx`:
- Around line 376-390: Extract the repeated search-only expression into an
isSearchOnly constant before the JSX, then use it for the EmptyState title,
message, and action label conditions. Preserve the existing condition and
handleClearFilters behavior.
- Around line 161-176: The categoryFilters state-to-URL effect causes
unnecessary replace navigations and overrides browser history restoration.
Remove that effect, keep the URL-to-state synchronization effect, and update
handleCategoryToggle and handleCategoryClear to set categoryFilters and the
categories query parameter together, matching the existing
handleStatusFilterChange pattern.

In `@frontend/src/index.css`:
- Around line 2058-2079: Refactor the .chip-emphasis rule to contain only its
differing background, color, and border declarations, relying on the existing
.chip class for shared layout, spacing, typography, and shape styles; preserve
the existing chip chip-emphasis JSX usage.
- Around line 1951-1960: Consolidate the duplicate CSS definitions for .chip,
.chip-emphasis, .chip-row, and .board-layout in index.css by merging shared
properties into their existing primary rules and removing the later duplicate
declarations, including the responsive .board-layout redefinition. Preserve the
intended board/category-specific styles and responsive behavior without relying
on source-order overrides.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 46a51b3c-cb98-4318-b293-f031c4421a1f

📥 Commits

Reviewing files that changed from the base of the PR and between 3e2dd95 and 0d820dd.

📒 Files selected for processing (5)
  • .kilo/kilo.jsonc
  • frontend/src/components/CampaignsTable.tsx
  • frontend/src/components/CategoryFilterSidebar.tsx
  • frontend/src/components/campaignsTableUtils.ts
  • frontend/src/index.css

Comment thread frontend/src/components/CampaignsTable.tsx
Comment on lines +39 to +40
const isMobile = useMediaQuery("(max-width: 767px)");
const [isOpen, setIsOpen] = useState(!isMobile);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

isOpen never tracks isMobile.

useMediaQuery returns false on the first render (it resolves inside an effect), so isOpen always initializes to true and is never re-derived. On mobile the list renders expanded on load, and rotating/resizing across the 767px breakpoint leaves the state stale.

🔧 Proposed fix
-import { useState } from "react";
+import { useEffect, useState } from "react";
@@
   const isMobile = useMediaQuery("(max-width: 767px)");
-  const [isOpen, setIsOpen] = useState(!isMobile);
+  const [isOpen, setIsOpen] = useState(true);
+
+  useEffect(() => {
+    setIsOpen(!isMobile);
+  }, [isMobile]);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const isMobile = useMediaQuery("(max-width: 767px)");
const [isOpen, setIsOpen] = useState(!isMobile);
const isMobile = useMediaQuery("(max-width: 767px)");
const [isOpen, setIsOpen] = useState(true);
useEffect(() => {
setIsOpen(!isMobile);
}, [isMobile]);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/components/CategoryFilterSidebar.tsx` around lines 39 - 40,
Update the state initialization and responsive behavior in CategoryFilterSidebar
so the filter starts closed when the media query resolves to mobile, rather than
relying on the initial false value. Keep isOpen synchronized with isMobile when
the breakpoint changes, including resize or rotation across 767px, while
preserving user-controlled open/closed state when the viewport remains
unchanged.

Comment thread frontend/src/components/CategoryFilterSidebar.tsx
@drips-wave

drips-wave Bot commented Jul 29, 2026

Copy link
Copy Markdown

@DanbabaJr Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

- add Storybook for component documentation
  - install @storybook/react-vite, @chromatic-com/storybook, and related addons
  - configure .storybook/main.ts for GitHub Pages base path
  - add stories for CampaignCard, ToastContainer, FundingProgress, Countdown, PledgeForm, ContributorList
  - add missing components: FundingProgress, Countdown, PledgeForm, ContributorList
  - add DesignTokens.doc story documenting CSS custom properties
  - add deploy-storybook.yml workflow to deploy to GitHub Pages
- automate changelog via conventional commits
  - add @commitlint/cli and @commitlint/config-conventional
  - add .commitlintrc.json enforcing conventional commit types
  - add .husky/commit-msg hook to block non-conforming commits
  - update PR template with commit type selector
  - update release-please-config.json with breaking change keywords

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 9

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/PULL_REQUEST_TEMPLATE.md:
- Line 16: Update the `docs` checklist label in the pull request template to use
the hyphenated wording “Documentation-only changes.”

In @.github/workflows/deploy-storybook.yml:
- Line 21: Update the actions/checkout@v4 step in the workflow to set
persist-credentials to false, while preserving the existing explicit
github_token used by peaceiris/actions-gh-pages.
- Around line 29-32: Update the Storybook deployment step using
peaceiris/actions-gh-pages so it uses the supported v4 action and publishes the
generated frontend/storybook-static directory instead of resolving publish_dir
from the repository root.

In `@frontend/package.json`:
- Line 14: Update the test-storybook script in package.json to invoke the
installed Vitest Storybook project, using the project-specific Vitest command
such as vitest --project=storybook. Do not leave it pointing to the unavailable
test-storybook runner.

In `@frontend/src/components/FundingProgress.tsx`:
- Around line 15-23: Update the token-progress condition in FundingProgress so
multiple accepted tokens render token bars only when balances were actually
provided; do not default tokenBalances to an object that makes the check always
truthy. Preserve the percentFunded overall-progress fallback when tokenBalances
is absent.

In `@frontend/src/components/PledgeForm.tsx`:
- Line 27: Update PledgeForm’s acceptedTokens initialization to fall back to
campaign.acceptedTokens when the prop is omitted, then use that resolved list
for selected-token derivation and token-option rendering. Preserve
campaign.assetCode behavior only when neither source provides accepted tokens.
- Around line 82-91: Update the claim button handler in PledgeForm’s onClaim
flow to await the returned promise and catch rejected claim requests. Surface
the caught error through the component’s existing claim-error feedback
mechanism, while preserving the current campaign argument and button behavior.
- Line 1: Update the imports in PledgeForm so useState is imported as a runtime
value rather than through the type-only import, while keeping FormEvent
type-only. Ensure the component’s direct useState call resolves at runtime.

In `@release-please-config.json`:
- Around line 31-32: Remove the unsupported breaking-change-keywords property
from the release-please configuration, leaving the surrounding configuration and
official schema-compatible options unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: c0145508-d590-43cd-8210-1f75e7813b14

📥 Commits

Reviewing files that changed from the base of the PR and between 0d820dd and ab4d7a2.

📒 Files selected for processing (18)
  • .commitlintrc.json
  • .github/PULL_REQUEST_TEMPLATE.md
  • .github/workflows/deploy-storybook.yml
  • .gitignore
  • .husky/commit-msg
  • frontend/.storybook/main.ts
  • frontend/package.json
  • frontend/src/components/ContributorList.stories.tsx
  • frontend/src/components/ContributorList.tsx
  • frontend/src/components/Countdown.stories.tsx
  • frontend/src/components/Countdown.tsx
  • frontend/src/components/DesignTokens.stories.tsx
  • frontend/src/components/FundingProgress.stories.tsx
  • frontend/src/components/FundingProgress.tsx
  • frontend/src/components/PledgeForm.stories.tsx
  • frontend/src/components/PledgeForm.tsx
  • package.json
  • release-please-config.json

Comment thread .github/PULL_REQUEST_TEMPLATE.md
Comment thread .github/workflows/deploy-storybook.yml
Comment on lines +29 to +32
- uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./storybook-static

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== workflow files =="
git ls-files '.github/workflows/*' || true

echo "== target workflow excerpt =="
if [ -f .github/workflows/deploy-storybook.yml ]; then
  cat -n .github/workflows/deploy-storybook.yml
else
  echo "target workflow not found"
fi

echo "== search for storybook-static usage and defaults/working-directory =="
rg -n "storybook-static|defaults:\s*run:\s*working-directory|working-directory:|uses: peaceiris/actions-gh-pages|build-storybook|storybook" -S .

echo "== git status/stat =="
git status --short || true
git diff --stat || true

Repository: ritik4ever/stellar-goal-vault

Length of output: 3787


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== frontend package scripts and config files =="
cat -n frontend/package.json

echo "== storybook config files =="
git ls-files frontend | rg '(^|/)(.storybook|storybook\.config|vite\.config|package\.json)$' || true

for f in frontend/.storybook/main.ts frontend/.storybook/main.js frontend/.storybook/main.cjs frontend/.storybook/main.mjs frontend/.storybook/preview.ts frontend/.storybook/preview.js frontend/.storybook/preview.cjs frontend/.storybook/preview.mjs frontend/vite.config.ts frontend/vite.config.js frontend/package.json; do
  if [ -f "$f" ]; then
    echo "--- $f"
    cat -n "$f"
  fi
done

echo "== action usage refs =="
rg -n "peaceiris/actions-gh-pages" .github/workflows packages.json package.json 2>/dev/null || true

Repository: ritik4ever/stellar-goal-vault

Length of output: 5773


🌐 Web query:

GitHub Actions workflow syntax defaults.run.working-directory apply only to run steps

💡 Result:

Yes, the GitHub Actions workflow syntax for defaults.run.working-directory applies exclusively to run steps [1][2][3]. According to official GitHub documentation, the defaults.run keyword is used to provide default shell and working-directory options specifically for all run steps within a workflow or a job [1][4][5]. This setting does not affect other types of steps, such as those that use uses to invoke actions [6]. Actions executed via uses manage their own execution environment and are not impacted by the defaults.run configuration [6]. To summarize the scope: - It applies to run steps (commands executed directly in the shell) [1][2]. - It does not apply to steps that utilize uses (actions) [6]. - You can set these defaults at the workflow level (under defaults:) or override them at the job level (under jobs.<job_id>.defaults:) [1][2][3]. Job-level settings take precedence over workflow-level settings [1][3].

Citations:


🌐 Web query:

peaceiris actions-gh-pages v3 publish_dir working directory behavior

💡 Result:

In peaceiris/actions-gh-pages (including v3), the publish_dir option specifies the source directory within your repository that contains the static files you wish to deploy to the gh-pages branch [1][2]. The contents of this specified directory are copied to the root of the target branch (gh-pages by default) [1][3]. Key behaviors regarding publish_dir include: 1. Default Directory: If not specified, the action defaults to using a directory named public in the root of your repository [1][3]. 2. Path Resolution: The path provided to publish_dir is relative to the workspace root (GITHUB_WORKSPACE) [4][5]. 3. Repository Root Interaction: If you set publish_dir to. (the repository root), the action may inadvertently attempt to delete or modify the.git directory within the workspace, which can cause deployment failures [4]. It is generally recommended to use a dedicated subdirectory (e.g.,./dist or./public) for your build artifacts to avoid this [6]. 4. Cleanup Behavior: By default, the action removes existing files in the target branch before deploying the new contents from publish_dir [7]. You can use the keep_files option if you wish to preserve existing files in the target branch [8][7]. For complex setups where you need to deploy specific files or handle directories already present in the workspace, common practices include creating a dedicated build output directory or using a post-build step to copy all necessary assets into a single directory before calling the action [6][5].

Citations:


🌐 Web query:

peaceiris actions-gh-pages v4 README publish_dir

💡 Result:

In the peaceiris/actions-gh-pages version 4 GitHub Action, the publish_dir input specifies the source directory containing the static files you wish to deploy to GitHub Pages [1][2]. Key details regarding publish_dir include: - Function: It defines the directory from which the action will copy and deploy files [1][3]. - Default Value: The default directory is./public [1][2][4]. - Behavior: Only the contents of the specified directory are pushed to the target branch (which defaults to gh-pages) [1][3]. Example usage in a workflow file: - name: Deploy uses: peaceiris/actions-gh-pages@v4 with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir:./public

Citations:


Publish the generated Storybook directory and use a supported deploy action.

defaults.run.working-directory only affects run steps, so peaceiris/actions-gh-pages receives ./storybook-static at the repository root. Storybook is configured to emit frontend/storybook-static, so update publish_dir and move to the supported v4 artifact.

Proposed fix
-      - uses: peaceiris/actions-gh-pages@v3
+      - uses: peaceiris/actions-gh-pages@v4
         with:
           github_token: ${{ secrets.GITHUB_TOKEN }}
-          publish_dir: ./storybook-static
+          publish_dir: ./frontend/storybook-static
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./storybook-static
- uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./frontend/storybook-static
🧰 Tools
🪛 actionlint (1.7.12)

[error] 29-29: the runner of "peaceiris/actions-gh-pages@v3" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/deploy-storybook.yml around lines 29 - 32, Update the
Storybook deployment step using peaceiris/actions-gh-pages so it uses the
supported v4 action and publishes the generated frontend/storybook-static
directory instead of resolving publish_dir from the repository root.

Source: Linters/SAST tools

Comment thread frontend/package.json
Comment on lines +15 to +23
acceptedTokens = [],
tokenBalances = {},
}: FundingProgressProps) {
return (
<div className="campaign-progress">
<div className="progress-copy">
{pledgedAmount} / {targetAmount} {acceptedTokens.length > 1 ? 'Tokens' : assetCode}
</div>
{acceptedTokens.length > 1 && tokenBalances ? (

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Preserve the overall-progress fallback when balances are absent.

Defaulting tokenBalances to {} makes the condition always truthy. A caller providing multiple accepted tokens without balances gets misleading zero-percent token bars instead of percentFunded.

Proposed fix
-  tokenBalances = {},
+  tokenBalances,
...
-      {acceptedTokens.length > 1 && tokenBalances ? (
+      {acceptedTokens.length > 1 && tokenBalances ? (
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
acceptedTokens = [],
tokenBalances = {},
}: FundingProgressProps) {
return (
<div className="campaign-progress">
<div className="progress-copy">
{pledgedAmount} / {targetAmount} {acceptedTokens.length > 1 ? 'Tokens' : assetCode}
</div>
{acceptedTokens.length > 1 && tokenBalances ? (
acceptedTokens = [],
tokenBalances,
}: FundingProgressProps) {
return (
<div className="campaign-progress">
<div className="progress-copy">
{pledgedAmount} / {targetAmount} {acceptedTokens.length > 1 ? 'Tokens' : assetCode}
</div>
{acceptedTokens.length > 1 && tokenBalances ? (
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/components/FundingProgress.tsx` around lines 15 - 23, Update the
token-progress condition in FundingProgress so multiple accepted tokens render
token bars only when balances were actually provided; do not default
tokenBalances to an object that makes the check always truthy. Preserve the
percentFunded overall-progress fallback when tokenBalances is absent.

@@ -0,0 +1,107 @@
import type { FormEvent, useState } from 'react';

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/sh
rg -n -P '^import\s+type\s+\{[^}]*\buseState\b' frontend/src/components/PledgeForm.tsx
rg -n '\buseState\s*\(' frontend/src/components/PledgeForm.tsx

Repository: ritik4ever/stellar-goal-vault

Length of output: 313


🏁 Script executed:

#!/bin/sh
set -eu

printf '--- PledgeForm relevant section ---\n'
sed -n '1,120p' frontend/src/components/PledgeForm.tsx

printf '\n--- TypeScript config flags affecting import-namespace/type-only behavior ---\n'
find . -maxdepth 3 -path './frontend/**' -o -path './node_modules/**' -prune 2>/dev/null | grep -E '(^|/)(tsconfig.*\.json|package\.json)$' | while read -r f; do
  if [ -f "$f" ]; then
    sed -n '1,220p' "$f" | grep -n -E '"importsNotUsedAsValues"|"verbatimModuleSyntax"|"isolatedModules"|"noUnusedLocals"|"type":"module"|typeOnly|tsx|jsx' || true
  fi
done

printf '\n--- React imports in nearby files ---\n'
rg -n "^import (?:type )?\\{[^\\n]*useState\\}" frontend/src -g '*.tsx' -g '*.ts' | head -50

Repository: ritik4ever/stellar-goal-vault

Length of output: 258


🏁 Script executed:

#!/bin/sh
set -eu

printf '%s\n' '--- PledgeForm relevant section ---'
sed -n '1,120p' frontend/src/components/PledgeForm.tsx

printf '%s\n' ''
printf '%s\n' '--- TypeScript config flags affecting import behavior ---'
find . -maxdepth 3 \( -path './node_modules/*' -prune \) -o \( -type f \( -name 'tsconfig*.json' -o -name 'package.json' \) \) -print | sort | while read -r f; do
  if [ -f "$f" ]; then
    printf '%s\n' "--- $f ---"
    sed -n '1,220p' "$f" | grep -n -Ei '"importsNotUsedAsValues"|"verbatimModuleSyntax"|"isolatedModules"|"noUnusedLocals"|"type":"module"|importsNotUsedAsValues|verbatimModuleSyntax|isolatedModules|noUnusedLocals|typeOnly|tsx|jsx' || true
  fi
done

printf '%s\n' ''
printf '%s\n' '--- useState import usage in frontend source ---'
rg -n "^import (?:type )?\\{[^\\n]*useState\\}" frontend/src -g '*.tsx' -g '*.ts' | head -80 || true

printf '%s\n' ''
printf '%s\n' '--- runtime-state check if tsconfig exists ---'
if [ -f frontend/tsconfig.json ]; then cat frontend/tsconfig.json; fi
if [ -f tsconfig.json ]; then cat tsconfig.json; fi

Repository: ritik4ever/stellar-goal-vault

Length of output: 5170


🌐 Web query:

TypeScript import type erases type imports used at runtime error TS2455

💡 Result:

The error TS2455, as described in your query, relates to the fundamental behavior of the import type syntax in TypeScript. It is important to clarify that import type is a compile-time-only construct guaranteed to be fully erased from the emitted JavaScript [1][2]. If you are encountering an error related to import type being "erased at runtime," it is likely because you are attempting to use an imported type as a value in your code [3][4]. Because import type declarations are completely removed during transpilation, the imported identifier does not exist in the generated JavaScript code [1][3]. Consequently, using it as a value (e.g., new MyType() or console.log(MyType)) is invalid and will trigger a TypeScript error [3][4]. To resolve this issue: 1. Check for Value Usage: Ensure that any identifier imported via import type is used only in type positions (e.g., in type annotations, implements clauses, or generic arguments) [1][2]. 2. Switch to Regular Imports: If you need to use the imported identifier as a value at runtime, you must use a standard import statement (e.g., import { MyValue } from './module') instead of import type [3][4]. 3. Module System Considerations: Note that using import or import type statements at the top level of a file will cause TypeScript to treat the file as a module [5][6]. If you are in a non-module environment or trying to mix ES modules and CommonJS, this can sometimes lead to module resolution errors [5][7]. In some specific cases where you need to reference a type without triggering module-level side effects or resolution issues, you can use the inline import() syntax: type MyType = import('./module').MyType; [5][6] If you believe you are seeing TS2455 specifically in a context that does not match this, please double-check the exact error message, as TS2455 is not a standard, commonly cited code for "import type erasure"; standard behavior for type-only imports is to simply be removed without error unless they are misused as values [3][2]. If the error persists, it may be a misconfiguration of your module resolution settings or a confusion with other module-related errors [5][7].

Citations:


Import useState as a runtime value.

useState is imported with import type, but the component calls it directly. Split the type import from the runtime import so useState is available at runtime.

Proposed fix
-import type { FormEvent, useState } from 'react';
+import { useState } from 'react';
+import type { FormEvent } from 'react';
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import type { FormEvent, useState } from 'react';
import { useState } from 'react';
import type { FormEvent } from 'react';
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/components/PledgeForm.tsx` at line 1, Update the imports in
PledgeForm so useState is imported as a runtime value rather than through the
type-only import, while keeping FormEvent type-only. Ensure the component’s
direct useState call resolves at runtime.

isSubmitting = false,
isPledgePending = false,
pledgeError = null,
acceptedTokens = [],

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Default token choices from the campaign.

When the optional acceptedTokens prop is omitted, multi-token campaigns render no selector and always pledge campaign.assetCode. Fall back to campaign.acceptedTokens before deriving the selected token and rendering options.

Proposed fix
-  const selectedToken = token || campaign.assetCode;
+  const availableTokens = acceptedTokens.length > 0
+    ? acceptedTokens
+    : campaign.acceptedTokens;
+  const selectedToken = token || (
+    availableTokens.includes(campaign.assetCode)
+      ? campaign.assetCode
+      : availableTokens[0] ?? campaign.assetCode
+  );
...
-      {acceptedTokens.length > 1 && (
+      {availableTokens.length > 1 && (
...
-            {acceptedTokens.map((token) => (
+            {availableTokens.map((token) => (

Also applies to: 36-36, 62-69

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/components/PledgeForm.tsx` at line 27, Update PledgeForm’s
acceptedTokens initialization to fall back to campaign.acceptedTokens when the
prop is omitted, then use that resolved list for selected-token derivation and
token-option rendering. Preserve campaign.assetCode behavior only when neither
source provides accepted tokens.

Comment on lines +82 to +91
{onClaim && (
<button
className="btn-ghost"
type="button"
disabled={isSubmitting || !campaign.progress.canClaim || !connectedWallet || connectedWallet !== campaign.creator || !walletReady}
onClick={() => { void onClaim(campaign); }}
>
Claim vault
</button>
)}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Handle rejected claim requests.

Line 87 discards onClaim’s promise. A failed claim becomes an unhandled rejection with no feedback; catch it and surface a claim error.

Proposed fix
-            onClick={() => { void onClaim(campaign); }}
+            onClick={() => {
+              void onClaim(campaign).catch((error) => {
+                setSubmitError(error instanceof Error ? error.message : 'Claim failed');
+              });
+            }}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{onClaim && (
<button
className="btn-ghost"
type="button"
disabled={isSubmitting || !campaign.progress.canClaim || !connectedWallet || connectedWallet !== campaign.creator || !walletReady}
onClick={() => { void onClaim(campaign); }}
>
Claim vault
</button>
)}
{onClaim && (
<button
className="btn-ghost"
type="button"
disabled={isSubmitting || !campaign.progress.canClaim || !connectedWallet || connectedWallet !== campaign.creator || !walletReady}
onClick={() => {
void onClaim(campaign).catch((error) => {
setSubmitError(error instanceof Error ? error.message : 'Claim failed');
});
}}
>
Claim vault
</button>
)}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/components/PledgeForm.tsx` around lines 82 - 91, Update the
claim button handler in PledgeForm’s onClaim flow to await the returned promise
and catch rejected claim requests. Surface the caught error through the
component’s existing claim-error feedback mechanism, while preserving the
current campaign argument and button behavior.

Comment on lines +31 to +32
],
"breaking-change-keywords": ["BREAKING CHANGE:"]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

schema="$(mktemp)"
trap 'rm -f "$schema"' EXIT

curl -fsSL \
  'https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json' \
  > "$schema"

jq -e '.properties["breaking-change-keywords"]' "$schema" >/dev/null

Repository: ritik4ever/stellar-goal-vault

Length of output: 167


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

printf '--- release-please-config.json relevant lines ---\n'
cat -n release-please-config.json | sed -n '1,80p'

printf '\n--- release workflow action pins ---\n'
if [ -f .github/workflows/release.yml ]; then
  cat -n .github/workflows/release.yml | sed -n '1,220p'
else
  echo ".github/workflows/release.yml not found"
fi

printf '\n--- search for schema/config references ---\n'
rg -n '"breaking-change-keywords"|release-please|config-file|schema|additionalProperties|properties' .github release-please-config.json 2>/dev/null || true

Repository: ritik4ever/stellar-goal-vault

Length of output: 258


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

printf '%s\n' '--- release-please-config.json relevant lines ---'
cat -n release-please-config.json | sed -n '1,80p'

printf '%s\n' ''
printf '%s\n' '--- release workflow action pins ---'
if [ -f .github/workflows/release.yml ]; then
  cat -n .github/workflows/release.yml | sed -n '1,220p'
else
  echo ".github/workflows/release.yml not found"
fi

printf '%s\n' ''
printf '%s\n' '--- search for schema/config references ---'
rg -n '"breaking-change-keywords"|release-please|config-file|schema|additionalProperties|properties' .github release-please-config.json 2>/dev/null || true

printf '%s\n' ''
printf '%s\n' '--- all tracked release-please config files ---'
git ls-files '*release-please-config.json' '*release-please*' config.json 2>/dev/null || true

Repository: ritik4ever/stellar-goal-vault

Length of output: 5744


🌐 Web query:

google-github-actions release-please-action v4 breaking-change-keywords config-file schemas config.json

💡 Result:

The release-please-action v4 requires the use of a manifest-based configuration rather than many of the legacy action inputs [1][2]. Regarding "breaking-change-keywords," release-please follows the Conventional Commits specification by default [3][4]. According to this standard, breaking changes are indicated by appending an exclamation mark (!) to the type/scope (e.g., feat!: or fix!:) or by using a footer with "BREAKING CHANGE:" [5]. There is no explicit "breaking-change-keywords" configuration option in the current release-please-config.json schema [6]. Instead, the tool automatically detects breaking changes based on these standard Conventional Commit patterns [5]. Key details regarding v4 and configuration: 1. Migration to googleapis: Development has moved from google-github-actions/release-please-action to googleapis/release-please-action [5][7]. Users should update their workflows to use the new repository [5][3]. 2. Config File Schema: The official configuration is defined in release-please-config.json [6]. The schema for this file is maintained by the upstream release-please project [6]. You can validate your configuration against the official schema located at https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json [6][8]. 3. Configuration Format: In v4, most configuration is handled via a release-please-config.json file in your repository [3][9]. The action input config-file allows you to specify the path to this file (defaulting to release-please-config.json) [3][10]. 4. Inline Overrides: If you prefer not to use a separate configuration file for simple setups, you can use the config-overrides-json input to provide configuration options as a JSON string directly within your workflow file [9]. For advanced configuration, such as setting custom changelog sections or release types, refer to the official manifest-releaser documentation [3][11].

Citations:


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

schema="$(mktemp)"
trap 'rm -f "$schema"' EXIT

curl -fsSL \
  'https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json' \
  > "$schema"

printf '%s\n' '--- top-level breaking-change-keywords property ---'
jq '.properties["breaking-change-keywords"]' "$schema"

printf '%s\n' ''
printf '%s\n' '--- property names containing breaking-change or changelog ---'
jq -r '.properties | to_entries[] | select(.key|test("break|change|changelog|packages|changelog-path"; "i")) | .key' "$schema"

printf '%s\n' ''
printf '%s\n' '--- package-level properties containing changelog/breaking/change ---'
jq -r '.properties.packages.type.description // empty, .properties.packages.properties | to_entries[] | select(.key|test("break|change|changelog|package-name"; "i")) | .key' "$schema"

printf '%s\n' ''
printf '%s\n' '--- schema additionalProperties settings ---'
jq -r '{top: .additionalProperties, packages: .properties.packages.properties."additionalProperties"}' "$schema"

Repository: ritik4ever/stellar-goal-vault

Length of output: 527


Remove the unsupported breaking-change-keywords configuration.

release-please-config.json declares the official release-please schema, and that schema does not define breaking-change-keywords. Release Please follows Conventional Commits breaking-change handling (! in the header or BREAKING CHANGE: footer), so this custom entry is unnecessary and can make config validation fail or this option be ignored.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@release-please-config.json` around lines 31 - 32, Remove the unsupported
breaking-change-keywords property from the release-please configuration, leaving
the surrounding configuration and official schema-compatible options unchanged.

Source: MCP tools

@ritik4ever

Copy link
Copy Markdown
Owner

Hi @DanbabaJr,

This PR could not be merged because it has merge conflicts with the target branch.

Please resolve the merge conflicts, push the updated changes, and the PR can be reviewed and merged.

Thank you!

1 similar comment
@ritik4ever

Copy link
Copy Markdown
Owner

Hi @DanbabaJr,

This PR could not be merged because it has merge conflicts with the target branch.

Please resolve the merge conflicts, push the updated changes, and the PR can be reviewed and merged.

Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants